package service

import (
	"encoding/json"
	"github.com/pkg/errors"
	"github.com/spf13/cast"
	"gorm.io/gorm"
	"time"
	"zsc-boot/app/customer/model"
	"zsc-boot/app/customer/model/request"
	msgSvc "zsc-boot/app/message/service"
	layerModel "zsc-boot/app/system_layer/model"
	layerSvc "zsc-boot/app/system_layer/service"
	"zsc-boot/core"
	"zsc-boot/core/orm"
	"zsc-boot/core/utils"
)

//http://175.178.192.160:9082/api/customer?id=75359

type CustomerSvc struct {
}

// GetUserId 获取用户id
func (c *CustomerSvc) GetUserId(raw model.CustomerImportLog) (uint, error) {
	var (
		userInfo layerModel.ServiceUser
	)
	db := orm.GetDb().Model(&layerModel.ServiceUser{}).
		Where("customer_len < customer_cap").
		Where("day_cap > today_len and is_active = ?", true)

	//处理角色权限
	var roleIds []uint
	_ = json.Unmarshal(raw.ChannelInfo.RoleIds, &roleIds)
	if len(roleIds) > 0 {
		db.Where("role_id in (?)", roleIds)
	}

	if err := db.Order("today_len asc").First(&userInfo).Error; err != nil {
		return 0, err
	}
	if userInfo.ID == 0 {
		return 0, errors.New("无可分配用户")
	}
	return userInfo.ID, nil
}

func (c *CustomerSvc) AutoAssigned() error {

	//找出所有需要分配的客户
	var rawCustomer []model.CustomerImportLog
	if err := orm.GetDb().Where("is_allocation = ?", false).
		Preload("ChannelInfo").
		Order("id desc").Find(&rawCustomer).Error; err != nil {
		return err
	}

	if len(rawCustomer) > 0 {
		var ids []uint

		if err := orm.GetDb().Model(&layerModel.ServiceUser{}).Pluck("id", &ids).Error; err != nil {
			return err
		}
		//修正员工名下的客户数量
		var userCustomerCount []model.UserCustomerCount
		if err := orm.GetDb().Model(&model.Customer{}).Where("user_id in ?", ids).Group("user_id").Select("user_id as id,count(*) as customer_len").
			Find(&userCustomerCount).Error; err != nil {
			return err
		}

		//拼sql
		for _, v := range userCustomerCount {
			if err := orm.GetDb().Model(&layerModel.ServiceUser{}).Where("id = ?", v.UserId).
				Update("customer_len", v.Count).Error; err != nil {
				return err
			}
		}
	}

	for _, customer := range rawCustomer {
		//处理重复
		var customerModel model.Customer
		if err := orm.GetDb().Where("mobile = ? ", customer.Mobile).
			Find(&customerModel).Error; err != nil {
			return err
		}

		if customerModel.ID != 0 {
			customerModel.FollowStatus = "新线索"
			customerModel.UpdateUid = 0
			customerModel.Name = customerModel.Name + "_重复"

			oldTag := make(map[string]any)
			_ = json.Unmarshal(customerModel.Tag, &oldTag)
			oldTag["is_repeated"] = true
			str, _ := json.Marshal(oldTag)
			customerModel.Tag = str
			customerModel.CreatedAt = orm.LocalTime(time.Now())
			customerModel.AssignedTime = model.CustomerTime(time.Now().Unix())
			customerModel.IsNew = true
			customerModel.ChannelId = customer.ChannelId
			//如果未重复或者重复在公海中都需要获取员工id
			if customerModel.UserId == 0 {

				userId, err := c.GetUserId(customer)
				//获取可以使用的用户
				if err != nil {
					return err
				}
				if userId == 0 {
					if err = msgSvc.SendMessage(1, "无可分配用户了", nil, nil); err != nil && err.Error() != "客户端不在线" {
						return err
					}
					core.GetLogger().Error("无可分配用户了")
					return nil
				}
				customerModel.UserId = userId
				customerModel.FirstUserId = userId
			} else {
				customerModel.FirstUserId = customerModel.UserId
			}

		} else {
			userId, err := c.GetUserId(customer)
			if err != nil {
				return err
			}

			nowTime := time.Now()
			//构建写入数据
			tagMap := make(map[string]any)
			_ = json.Unmarshal(customer.Tag, &tagMap)
			var (
				companyName string
				realAmount  string
			)
			if v, ok := tagMap["companyName"]; ok {
				companyName = cast.ToString(v)
			}
			if v, ok := tagMap["realAmount"]; ok {
				realAmount = cast.ToString(v)
			}
			customerModel = model.Customer{
				Model:          orm.Model{},
				City:           customer.City,
				Name:           customer.Name,
				CompanyName:    companyName,
				RegisterAmount: 0,
				RealAmount:     realAmount,
				Mobile:         customer.Mobile,
				Remark:         customer.Remark,
				Sex:            customer.Sex,
				Age:            customer.Age,
				FollowStatus:   "新线索",
				UserId:         userId,
				ChannelId:      customer.ChannelId,
				AssignedTime:   model.CustomerTime(nowTime.Unix()),
				LastFollowTime: model.CustomerTime(nowTime.Unix()),
				IsBlack:        false,
				Tag:            customer.Tag,
				FirstUserId:    userId,
			}
			customerModel.ImportTime = model.CustomerTime(time.Time(customer.CreatedAt).Unix())
			customerModel.CreatedAt = customer.CreatedAt
		}

		if err := orm.GetDb().Transaction(func(tx *gorm.DB) error {

			if e := tx.Model(&layerModel.ServiceUser{}).Where("id = ?", customerModel.FirstUserId).
				Update("today_len", gorm.Expr("today_len+1")).Error; e != nil {
				return e
			}

			if err := tx.Save(&customerModel).Error; err != nil {
				return err
			}

			if customerModel.FirstUserId == 0 || customerModel.ID == 0 {
				return errors.New("信息缺失")
			}
			if err := tx.Model(&model.CustomerImportLog{}).Where("id = ?", customer.ID).
				Updates(map[string]interface{}{
					"is_allocation": true,
					"user_id":       customerModel.FirstUserId,
					"customer_id":   customerModel.ID,
				}).Error; err != nil {
				return err
			}

			if err := tx.Create(&model.CustomerFlowLog{
				CustomerId: customerModel.ID,
				NewUserId:  customerModel.UserId,
				Reason:     "新线索分配",
			}).Error; err != nil {
				return err
			}
			if err := msgSvc.SendMessage(int(customerModel.UserId), "有新的客户分配了", tx, nil); err != nil && err.Error() != "客户端不在线" {
				return err
			}
			return nil
		}); err != nil {
			return err
		}
	}
	return nil
}

// HideMobile 隐藏手机号逻辑
func (c *CustomerSvc) HideMobile(list []model.Customer) []model.Customer {
	for k, v := range list {
		if len(list[k].FollowLogs) == 11 {
			list[k].Mobile = v.Mobile[:3] + "****" + v.Mobile[7:]
			list[k].NotFollowDay = (time.Now().Unix() - int64(list[k].LastFollowTime)) / 86400
		}
	}
	return list
}

func (c *CustomerSvc) MyListNext(req request.CustomerListNextReq) (id, index int, err error) {
	db := orm.GetDb().Model(&model.Customer{}).Where("user_id = ?", req.UserId)
	db = req.BuildWhere(db)

	db = req.Order(db)
	var ids []int
	if err = db.Pluck("id", &ids).Error; err != nil {
		return
	}

	//找出下一个id
	for i := 0; i < len(ids); i++ {
		if ids[i] == req.Id {
			if req.IsPrevious {
				if i != 0 {
					return ids[i-1], req.Page, nil
				} else {
					return 0, req.Page, nil
				}
			} else {
				if i != len(ids)-1 {
					return ids[i+1], req.Page, nil
				} else {
					return 0, req.Page, nil
				}
			}
		}
	}
	return 0, 0, errors.New("定位失败")
}

func (c *CustomerSvc) MyList(req request.CustomerListReq) (list []model.Customer, count int64, err error) {
	db := orm.GetDb().Model(&model.Customer{}).Where("user_id = ?", req.UserId)
	db = req.BuildWhere(db)
	if err = db.Count(&count).Error; err != nil {
		return
	}

	db = req.Order(db)
	err = db.Offset(req.PageSize*(req.Page-1)).Limit(req.PageSize).Preload("ChannelInfo").Preload("UserInfo").
		Preload("FollowLogs", func(db *gorm.DB) *gorm.DB {
			return db.Order("id DESC")
		}).Preload("FollowLogs.UserInfo").Find(&list).Error
	return
}

func (c *CustomerSvc) AllList(req request.CustomerListReq, userInfo layerModel.ServiceUser) (
	list []model.Customer, count int64, err error) {
	db := orm.GetDb().Model(&model.Customer{})
	db = req.BuildWhere(db)

	//超管不受限制
	if userInfo.Role.Code != "root" {
		//权限控制
		userInfoList := layerSvc.ServiceUsersService.GetSubUsers(userInfo.ID)
		userIds := make([]uint, 0, len(userInfoList))
		if len(userInfoList) > 0 {
			for _, user := range userInfoList {
				userIds = append(userIds, user.ID)
			}
		} else {
			userIds = append(userIds, userInfo.ID) //自已的数据总是可以看的
		}

		db.Where("user_id in (?)", userIds)
	}

	//部门过滤
	if req.DepId != 0 {
		var dep layerModel.ServiceDepartment
		if err = orm.GetDb().Where("id = ?", req.DepId).Preload("Children.Children.Children").Find(&dep).Error; err != nil {
			return
		}
		userInfoList := layerSvc.ServiceUsersService.GetUserListByDep([]layerModel.ServiceDepartment{dep})
		userIds := make([]uint, 0, len(userInfoList))
		for _, user := range userInfoList {
			userIds = append(userIds, user.ID)
		}
		db.Where("user_id in (?)", userIds)
	}

	if req.IsNew != nil {
		db.Where("is_new = ?", *req.IsNew)
		if req.UserId != 0 {
			db.Where("user_id = ?", req.UserId)
		} else {
			db.Where("user_id <> 0")
		}
	} else {
		if req.UserId != 0 {
			db.Where("user_id = ?", req.UserId)
		}
	}

	if err = db.Count(&count).Error; err != nil {
		return
	}
	db = req.Order(db)
	db.Offset(req.PageSize*(req.Page-1)).Limit(req.PageSize).Preload("ChannelInfo").Preload("UserInfo").
		Preload("FollowLogs", func(db *gorm.DB) *gorm.DB {
			return db.Order("id DESC")
		}).Preload("FollowLogs.UserInfo").Find(&list)
	return
}

func (c *CustomerSvc) PublicList(req request.CustomerListReq) (
	list []model.Customer, count int64, err error) {
	db := orm.GetDb().Model(&model.Customer{}).Where("user_id = 0")

	db = req.BuildWhere(db)
	//未跟进天数

	if err = db.Count(&count).Error; err != nil {
		return
	}

	db.Offset(req.PageSize*(req.Page-1)).Limit(req.PageSize).Order("updated_at desc").Preload("ChannelInfo").Preload("UserInfo").
		Preload("FollowLogs", func(db *gorm.DB) *gorm.DB {
			return db.Order("id DESC")
		}).Preload("FollowLogs.UserInfo").Find(&list)
	return
}

func (c *CustomerSvc) PublicListNext(req request.CustomerListNextReq) (
	id int, index int, err error) {
	//超管不受限制
	db := orm.GetDb().Model(&model.Customer{}).Where("user_id = 0")

	db = req.BuildWhere(db)

	//找出下一个id
	var Ids []int

	offset := (req.Page - 1) * req.PageSize
	if req.Page > 1 {
		offset--
	}

	if err = db.Offset(offset).Limit(req.PageSize+1).Order("updated_at desc").Pluck("id", &Ids).Error; err != nil {
		return
	}

	//找出下一个id
	for i := 0; i < len(Ids); i++ {
		if Ids[i] == req.Id {
			if req.IsPrevious {
				if i == 0 {
					id = 0
					return
				}
				id = Ids[i-1]
				if i-1 == 0 && req.Page != 1 {
					index = -1
				}
			} else {
				id = Ids[i+1]
				if i+1 == len(Ids) {
					index = 1
				}
			}
			return
		}
	}
	return 0, 0, errors.New("找不到")
}

func (c *CustomerSvc) AllListNext(req request.CustomerListNextReq, userInfo layerModel.ServiceUser) (
	id int, index int, err error) {
	db := orm.GetDb().Model(&model.Customer{})
	//超管不受限制
	if userInfo.Role.Code != "root" {
		//权限控制
		userInfoList := layerSvc.ServiceUsersService.GetSubUsers(userInfo.ID)
		userIds := make([]uint, 0, len(userInfoList))
		if len(userInfoList) > 0 {
			for _, user := range userInfoList {
				userIds = append(userIds, user.ID)
			}
		} else {
			userIds = append(userIds, userInfo.ID) //自已的数据总是可以看的
		}

		db.Where("user_id in (?)", userIds)
	}

	if req.UserId != 0 {
		db.Where("user_id = ?", req.UserId)
	}

	//部门过滤
	if req.DepId != 0 {
		var dep layerModel.ServiceDepartment
		if err = orm.GetDb().Where("id = ?", req.DepId).Preload("Children.Children.Children").Find(&dep).Error; err != nil {
			return
		}
		userInfoList := layerSvc.ServiceUsersService.GetUserListByDep([]layerModel.ServiceDepartment{dep})
		userIds := make([]uint, 0, len(userInfoList))
		for _, user := range userInfoList {
			userIds = append(userIds, user.ID)
		}
		db.Where("user_id in (?)", userIds)
	}

	db = req.BuildWhere(db)
	db = req.Order(db)

	offset := (req.Page - 1) * req.PageSize
	if req.Page > 1 {
		offset--
	}

	//找出下一个id
	var Ids []int
	if err = db.Offset(offset).Limit(req.PageSize+1).Order("id desc").Pluck("id", &Ids).Error; err != nil {
		return
	}

	//找出下一个id
	//找出下一个id
	for i := 0; i < len(Ids); i++ {
		if Ids[i] == req.Id {
			if req.IsPrevious {
				if i == 0 {
					id = 0
					return
				}
				id = Ids[i-1]
				if i-1 == 0 && req.Page != 1 {
					index = -1
				}
			} else {
				id = Ids[i+1]
				if i+1 == len(Ids) {
					index = 1
				}
			}
			return
		}
	}
	return 0, 0, errors.New("找不到")
}

// BatchCollect 收藏
func (c *CustomerSvc) BatchCollect(req request.BatchCollect, userId int) error {
	//获取最大收藏数
	dict, err := layerSvc.GetDictByKey[[]uint]("collect-max")
	if err != nil {
		return err
	}

	//判断该用户收藏数是否超标
	return orm.GetDb().Transaction(func(tx *gorm.DB) error {
		if err = tx.Model(&model.Customer{}).Where("id in ?", req.Ids).
			Updates(map[string]any{
				"is_collect": req.IsCollect,
				"user_id":    userId,
			}).Error; err != nil {
			return err
		}

		var count int64
		if err = tx.Model(&model.Customer{}).Where("user_id = ? and is_collect = ?", userId, true).
			Count(&count).Error; err != nil {
			return err
		}

		if count > int64(dict[0]) && req.IsCollect == true {
			return errors.New("收藏超过最大客户限制")
		}
		return nil
	})
}

// Collect 收藏
func (c *CustomerSvc) Collect(req model.Customer) error {
	//获取最大收藏数
	dict, err := layerSvc.GetDictByKey[[]uint]("collect-max")
	if err != nil {
		return err
	}

	data, err := orm.Detail[model.Customer](int(req.ID))
	if err != nil {
		return err
	}

	//判断该用户收藏数是否超标
	if req.IsCollect == true {
		var count int64
		if err = orm.GetDb().Model(&model.Customer{}).Where("user_id = ?", data.UserId).
			Count(&count).Error; err != nil {
			return err
		}
		if count >= int64(dict[0]) {
			return errors.New("收藏额已满")
		}
	}
	return orm.GetDb().Model(&model.Customer{}).Where("id = ?", req.ID).
		Update("is_collect", req.IsCollect).Error
}

// BatchUpdate 批量修改api
func (c *CustomerSvc) BatchUpdate(req request.BatchUpdate, userId int) error {
	updateMap := make(map[string]interface{})
	if req.Delete {
		updateMap["deleted_at"] = time.Now().Format(time.DateTime)
	}
	if req.IsBlack != nil {
		updateMap["is_black"] = req.IsBlack
		updateMap["category"] = req.IsBlack
	}
	if req.Category != "" {
		updateMap["category"] = req.Category
	}
	if req.UserId != nil {
		if *req.UserId != 0 {
			//检查用户容量
			var userInfo layerModel.ServiceUser
			if err := orm.GetDb().Model(layerModel.ServiceUser{}).Where("id = ?", req.UserId).First(&userInfo).Error; err != nil {
				return err
			}
			if userInfo.IsActive == false {
				return errors.New("用户已离职")
			}

			var userCustomerNum int64
			if err := orm.GetDb().Model(&model.Customer{}).Where("user_id = ?", req.UserId).Count(&userCustomerNum).Error; err != nil {
				return err
			}
			userInfo.CustomerLen = uint(userCustomerNum)
			if err := orm.GetDb().Save(&userInfo).Error; err != nil {
				return err
			}

			if uint(len(req.Ids))+uint(userCustomerNum) > userInfo.CustomerCap {
				return errors.New("用户容量不够")
			}
		}

		updateMap["user_id"] = *req.UserId
		dateOnly, _ := time.ParseInLocation(time.DateOnly, time.Now().Format(time.DateOnly), time.Local)
		updateMap["last_follow_time"] = dateOnly.Unix()
		updateMap["assigned_time"] = time.Now().Unix()
		if req.IsNew == nil {
			updateMap["is_new"] = false
		} else {
			updateMap["is_new"] = req.IsNew
		}
	}

	return orm.GetDb().Transaction(func(tx *gorm.DB) error {
		//如果修改了归属人 则多走这些逻辑
		if req.UserId != nil {
			//找出所有受影响的客户
			var customerList []model.Customer
			if err := tx.Model(model.Customer{}).Where("id IN (?)", req.Ids).Find(&customerList).Error; err != nil {
				return err
			}

			//构建流转日志
			flowLog := make([]model.CustomerFlowLog, 0, len(customerList))
			for _, customer := range customerList {
				flowLog = append(flowLog, model.CustomerFlowLog{
					CustomerId: customer.ID,
					OldUserId:  customer.UserId,
					NewUserId:  *req.UserId,
					Reason:     "手动转移",
					UserId:     uint(userId),
				})
			}
			if err := tx.Create(&flowLog).Error; err != nil {
				return err
			}
		}

		//正式修改
		if err := tx.Model(&model.Customer{}).Where("id IN (?)", req.Ids).Updates(updateMap).Error; err != nil {
			return err
		}
		return nil
	})
}

// Detail 详情
func (c *CustomerSvc) Detail(id int, hideMobile bool) (res model.Customer, err error) {
	res, err = orm.Detail[model.Customer](id,
		"FollowLogs.CustomerInfo", "FollowLogs.UserInfo",
		"FlowLogs.OldUserInfo", "FlowLogs.NewUserInfo", "ChannelInfo")
	if err != nil {
		return
	}
	if hideMobile {
		res.Mobile = res.Mobile[:3] + "****" + res.Mobile[7:]
	}
	return
}

// Update 全量编辑
func (c *CustomerSvc) Update(req request.CustomerUpdate) (err error) {
	return orm.GetDb().Model(&model.Customer{}).Omit("mobile", "channel_id").
		Where("id = ?", req.ID).Updates(&req).Error
}

// Follow 跟进
func (c *CustomerSvc) Follow(req model.CustomerFollowLog) (err error) {
	unix, _ := time.ParseInLocation(time.DateOnly, time.Now().Format(time.DateOnly), time.Local)

	return orm.GetDb().Transaction(func(tx *gorm.DB) error {
		if err = tx.Model(&model.Customer{}).Where("id = ?", req.CustomerId).
			Update("last_follow_time", unix.Unix()).Error; err != nil {
			return err
		}
		return tx.Create(&req).Error
	})
}

func (c *CustomerSvc) Remind(req model.CustomerFollowRemind) (err error) {
	return orm.GetDb().Create(&req).Error
}

func (c *CustomerSvc) CronRemind() {
	core.GetLogger().Info("执行定时提醒")
	var list []model.CustomerFollowRemind
	if err := orm.GetDb().Model(&model.CustomerFollowRemind{}).
		Where("`date` = ?", time.Now().Format("2006-01-02 15:04")).Find(&list).Error; err != nil {
		core.GetLogger().Error("定时提醒客户跟进异常" + err.Error())
		return
	}

	for _, v := range list {
		if err := msgSvc.SendMessage(int(v.UserId), v.Content, nil, nil); err != nil {
			core.GetLogger().Error("定时提醒异常" + err.Error())
		}
	}
}

func (c *CustomerSvc) Clear(depList []layerModel.ServiceDepartment) {
	//获取全部清洗值
	var dictionary layerModel.Dictionary
	if err := orm.GetDb().Where("`key` = ?", "clean_day").First(&dictionary).Error; err != nil {
		core.GetLogger().Error("clean_day字典异常" + err.Error())
		return
	}
	var days []uint
	_ = json.Unmarshal(dictionary.Value, &days)

	for _, v := range depList {
		if len(v.Children) > 0 {
			c.Clear(v.Children)
		}
		userIds := make([]uint, 0, len(v.MembersList))
		for _, user := range v.MembersList {
			userIds = append(userIds, user.ID)
		}

		day := days[0]
		if *v.ClearDay != 0 {
			day = uint(*v.ClearDay)
		}

		if len(userIds) == 0 || day == 0 {
			continue
		}
		var customerList []model.Customer
		if err := orm.GetDb().Model(&model.Customer{}).
			Where("follow_status <> ? AND user_id IN (?) and ? - last_follow_time > ? and is_collect = ?",
				"已签约", userIds, time.Now().Unix(), int(*v.ClearDay)*86400, false).Find(&customerList).Error; err != nil {
			core.GetLogger().Error("清洗时服务异常:" + err.Error())
			return
		}
		if len(customerList) == 0 {
			continue
		}

		//构建流转日志
		var (
			customerFlowLogs []model.CustomerFlowLog
			customerIds      []uint
		)

		for _, customer := range customerList {
			customerIds = append(customerIds, customer.ID)
			customerFlowLogs = append(customerFlowLogs, model.CustomerFlowLog{
				CustomerId: customer.ID,
				NewUserId:  0,
				OldUserId:  customer.UserId,
				Reason:     "跟进过期清洗",
			})
		}
		if err := orm.GetDb().Transaction(func(tx *gorm.DB) error {
			if err := tx.Create(&customerFlowLogs).Error; err != nil {
				return err
			}
			if err := tx.Model(&model.Customer{}).Where("id IN (?)", customerIds).
				Updates(map[string]interface{}{
					"is_new":  false,
					"user_id": 0,
				}).Error; err != nil {
				return err
			}
			return nil
		}); err != nil {
			core.GetLogger().Error("清洗时服务异常:" + err.Error())
			return
		}

	}
}

func (c *CustomerSvc) CronClear() {
	core.GetLogger().Info("执行清洗逻辑")

	if err := orm.GetDb().Model(&layerModel.ServiceUser{}).Where("1 = 1").
		Updates(map[string]any{
			"today_len": 0,
		}).Error; err != nil {
		core.GetLogger().Error("重置数量异常:" + err.Error())
		return
	}

	//先获取顶层部门
	var depList []layerModel.ServiceDepartment
	if err := orm.GetDb().Where("parent_id = 0").
		Preload("Children.MembersList").
		Preload("Children.Children.MembersList").
		Preload("Children.Children.Children.MembersList").
		Find(&depList).Error; err != nil {
		core.GetLogger().Error("清洗时服务异常:" + err.Error())
		return
	}
	c.Clear(depList)
}

func (c *CustomerSvc) Export() (mobileList []string, err error) {
	if err = orm.GetDb().Model(&model.Customer{}).Select("mobile").
		Pluck("mobile", &mobileList).Error; err != nil {
		return
	}
	for k, _ := range mobileList {
		mobileList[k] = utils.MD5V([]byte(mobileList[k]))
	}
	return
}
